package com.wang.tool.dagre;

import com.wang.tool.dagre.node.DagreNode;
import com.wang.tool.common.SimpleException;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;

/**
 * @Description 动态构建器
 * @Author shaopeng
 * @Date 2021/10/25
 * @Version 1.0
 * @see DagreEngine
 * @see SimpleDagreBuilder#addNode
 * @see SimpleDagreBuilder#build
 */
public class SimpleDagreBuilder<T> {

    /**
     * 图引擎名
     */
    private String name = "UNKNOWN";

    /**
     * 主线程池
     */
    private ExecutorService mainExecutor;

    /**
     * 节点
     */
    private final Map<String, DagreNode<T>> nodeMap = new HashMap<>();


    /**
     * 节点选择器
     */
    private NodeSelector<T> nodeSelector = (engine, param, timeout) -> engine.getAllIds();


    /**
     * 注册节点
     *
     * @param nodes
     * @return
     */
    public SimpleDagreBuilder<T> addNode(DagreNode<T>... nodes) {
        if (nodes == null) {
            return this;
        }
        for (DagreNode<T> node : nodes) {
            if (node == null) {
                continue;
            }
            if (node.getId() == null) {
                throw new SimpleException(SimpleException.PARAM_INVALID, "nodeId can not be null");
            }
            nodeMap.put(node.getId(), node);
        }
        return this;
    }

    /**
     * 删除节点
     *
     * @param nodeIds
     * @return
     */
    public SimpleDagreBuilder<T> removeNode(String... nodeIds) {
        if (nodeIds == null) {
            return this;
        }
        for (String nodeId : nodeIds) {
            if (nodeId == null) {
                continue;
            }
            nodeMap.remove(nodeId);
        }
        return this;
    }


    public SimpleDagreBuilder<T> mainExecutor(ExecutorService mainExecutor) {
        this.mainExecutor = mainExecutor;
        return this;
    }

    public SimpleDagreBuilder<T> name(String name) {
        this.name = name;
        return this;
    }


    /**
     * 设置节点选择器
     *
     * @param nodeSelector
     * @return
     */
    public SimpleDagreBuilder<T> nodeSelector(NodeSelector<T> nodeSelector) {
        this.nodeSelector = nodeSelector;
        return this;
    }

    /**
     * 构建引擎
     *
     * @return
     * @throws SimpleException 依赖成环
     */
    public DagreEngine<T> build() throws SimpleException {
        if (getName() == null) {
            throw new IllegalArgumentException("dagreName can not be null");
        }
        if (getMainExecutor() == null) {
            throw new IllegalArgumentException("mainExecutor can not be null");
        }

        if (getNodeSelector() == null) {
            throw new IllegalArgumentException("nodeSelector can not be null");
        }
        DagreEngine<T> dagre = new DagreEngine<>();
        dagre.setName(getName());
        dagre.setMainExecutor(getMainExecutor());
        dagre.setNodeSelector(getNodeSelector());
        dagre.addNode(getNodeMap().values().toArray(new DagreNode[0]));
        //尝试冻结配置
        dagre.tryFreeze();
        return dagre;
    }


    public Map<String, DagreNode<T>> getNodeMap() {
        return nodeMap;
    }

    public ExecutorService getMainExecutor() {
        return mainExecutor;
    }


    public String getName() {
        return name;
    }

    public NodeSelector<T> getNodeSelector() {
        return nodeSelector;
    }

}
